#ifndef ZT_NET_H
#define ZT_NET_H

#include "my_fifo.h"
#include "SDSet.h"
//#include "zt_type.h"

#define MODBUS_WS_REG 0x6
#define MODBUS_WM_REG 0x10
#define MODBUS_RM_REG 0x03
#define CIN0L 0
#define CIN0H 1
#define CIN1L 2
#define CIN1H 3
#define CIN2L 4
#define CIN2H 5

#define S_RUN   3
#define S_STOP  2


#define SET_IP_ADDRESS 0
#define SET_IP_MASK_ADDRESS 2
//#define SET_MAC_ADDRESS 4
#define SET_DPORT_ADDRESS 4
#define SET_DR_ADDRESS 7
#define SET_PORT_ADDRESS 9
#define AD_RANGE_ADDRESS 10
#define AD_CH_ADDRESS 12
#define AD_CHRANGE_ADDRESS 14
#define GROUP_RATE_ADDRESS 16
#define S_RATE_ADDRESS 18
#define FRAME_GROUP_CNT 20 
#define HC_START_ADDRESS 22
#define HC_AUTOSEND_ADDRESS 23
#define ADZFCODE_ADDRESS 200
#define ADZCODE_ADDRESS 200
#define ADFCODE_ADDRESS 202
#define SD_IS_SAVE_ADDRESS 25
#define ETR_GROUP_COUNT_ADDRESS 26

#define DA_CH0_ADDRESS 26
#define DA_CH1_ADDRESS 28
#define DA_CH2_ADDRESS 30
#define DA_CH3_ADDRESS 32

#define DO_MODE_ADDRESS 34
#define IO_DIR_ADDRESS  35
#define IO_DO1T2_ADDRESS 36
#define IO_IO17T24_ADDRESS 37


#define CT_DIV1_ADDRESS 40  //计数器基准脉冲设定（测频用
#define CT_DIV2_ADDRESS 42
#define CT_DIV3_ADDRESS 44
#define CT_DIV4_ADDRESS 46
//#define CT_DIV5_ADDRESS 48
//#define CT_DIV6_ADDRESS 50
#define CT_MOD_ADDRESS 52

//#define AD_GAIN_ADDRESS 56

#define DA_CH0_MOD_ADDRESS 58
#define DA_CH1_MOD_ADDRESS 60
#define DA_CH2_MOD_ADDRESS 62
#define DA_CH3_MOD_ADDRESS 64

#define DA_CH0_ZERO_ADDRESS 67
#define DA_CH1_ZERO_ADDRESS 71
#define DA_CH2_ZERO_ADDRESS 75
#define DA_CH3_ZERO_ADDRESS 79

#define DA_CH0_FULL_ADDRESS 66
#define DA_CH1_FULL_ADDRESS 70
#define DA_CH2_FULL_ADDRESS 74
#define DA_CH3_FULL_ADDRESS 78

#define DA_CH0_MAX_ADDRESS 66
#define DA_CH0_MIN_ADDRESS 67
#define DA_CH1_MAX_ADDRESS 70
#define DA_CH1_MIN_ADDRESS 71
#define DA_CH2_MAX_ADDRESS 74
#define DA_CH2_MIN_ADDRESS 75
#define DA_CH3_MAX_ADDRESS 78
#define DA_CH3_MIN_ADDRESS 79

#define GET_SD_INFO 150
#define GET_FIFO_STATE 155

#define SET_WDT_ADDRESS 180

#define GET_STORAGE_INFO 188

#define TIME_ADDRESS 189

#define EC_CLEAR_ADDRESS 193

#define PWM_FREQ1_DIV_ADDRESS 80
#define PWM_FREQ2_DIV_ADDRESS 81
#define PWM_WIDE1_ADDRESS 88
#define PWM_WIDE2_ADDRESS 89
#define PWM_STEPCNT1_ADDRESS 96
#define PWM_STEPCNT2_ADDRESS 97
#define PWM_PHASE_ADDRESS 104
#define PWM_ENABLE_ADDRESS 105


//完全符合modbus标准功能3，支持任意寄存器个数的读取
#define MD_BEGIN_ADDRESS 256
//#define MD_AD_ONCE_ADDRESS 256 
//#define MD_CT_ONCE_ADDRESS 288
//#define MD_IO_ONCE_ADDRESS 310
#define MD_END_ADDRESS 290
//完全符合modbus标准功能3，支持任意寄存器个数的读取
#define IO_GET_ALL 291
#define AD_DATA_LAST_ADDRESS 512

#define ZTCMD_RESET 65535
#define ZTCMD_STARTNORET 65534
#define ZTCMD_SDSETFILE 65533
#define ZTCMD_SDGETFILE 65532
#define ZTCMD_SETOFFLINESRC 65531
#define ZTCMD_SETOFFLINESAVETV 65530

#define MODBUS_ERR_NOCMD			1
#define MODBUS_ERR_PARA				2
#define MODBUS_ERR_DATANOTREADY		4
#define MODBUS_ERR_NOPRIVILEGE			8

//这部分请参考各个MD**Buffer函数
#define MDBUFFER_AD_INX				0
#define MDBUFFER_CT_INX				AD_CH_COUNT
#define MDBUFFER_IO_INX				AD_CH_COUNT + CT_CH_COUNT * 2
#define MDBUFFER_EC_INX				AD_CH_COUNT + CT_CH_COUNT * 2 + 2;

struct modbus_hdr{
	U16 cmd_code;//用于modbus扩展用，当其值<32768时，表明命令为标准modbus，否则是自定义标准
	U16 ext_len;//用于modbus扩展用，当使用自定义标准时，表示后续字节长度
	U16 len;
	U8 id;
	U8 fc;
	U16 reg_addr;
	U16 reg_len;
	U8 byte_len;
	U16 data_hdr;//不能用，应该是对齐的问题
};

struct modbus_back{
	U16 cmd_code;//用于modbus扩展用，当其值<32768时，表明命令为标准modbus，否则是自定义标准
	U16 ext_len;//用于modbus扩展用，当使用自定义标准时，表示后续字节长度
	U16 len;
	U8 id;
	U8 fc;
	U8 byte_len;//当返回错误时，表示错误码，1，不支持的命令，2是地址或者寄存器错误（参数错误），4是数据没有准备好，
	U16 rd_back_byte_hdr;//不能用，应该是对齐的问题
};

#define HTONS(n) (U16)((((U16) (n)) << 8) | (((U16) (n)) >> 8))

typedef struct AD_PARA
{
	U32 enCh;//bit0~bit17对应AD1~AD18使能位
	int rangeInx;//AD采集范围索引，0 ±10V，1 ±5V，2 0~20mA
	I16 zCode[AD_CH_COUNT];//对零点原码值
	I16 fCode[AD_CH_COUNT];//对90%满度的原码值。比如±10V时，这是值就是9V对应的原码值
}AdPara, *PAdPara;

typedef struct IO_PARA
{
	int isFifo;
	U8 oGroupByte[4];
	int dir;
}IoPara;

#define LED_FLASH_COUNT				100000 / 10	//在100K时，100ms切换一次指示灯状态

typedef struct DEV_PARA
{
	int ip[4];
	int mk[4];
	int gt[4];
	int port;//命令端口号
	int dataPort;//主动发送端口号
	int fd;//设备ID
	int fd_pio;//GPIO
	int cmdFd;
	U16 freqDiv[AD_CH_COUNT];//通道分频系数
	U32 groupFreqDiv;//组分频系数
	int groupCnt;//组数，针对上下位机传输数据
	int groupBC;//每组数据字节数，针对上下位机传输数据
	int needSendBC;
	int kGroupCnt;//组数，针对从内核缓冲区读取数据
	int needRead;
	U8 autoSend;
	int netSock;
	int autoSendSock;
	int startMode;
	U32 etrCodeCount;//外触发采集组数
	U32 etrReadCount;//外触发指定组数时已经读取的组数
	U16 allChCount;
	int isPSync;
	int isStop;
	PSFIFO pSFifo;
	int errorCode;
	U16 mdBuffer[128];//储存所有不需要连续采集的数据。
	pthread_mutex_t mdLock;
	pthread_mutex_t ebiLock;
    pthread_mutex_t ledLock;
    pthread_mutex_t netLock;
    pthread_cond_t netCond;
	FILE* dataF;//数据文件句柄，如果其不为空，则说明需要写数据
	int firstRead;
	SDSet* pSDSet;
	SDInfo sdInfo;
	int isSave;
	int ledFlashCnt;//250K的时候20mS切换一次网络指示灯的状态
	int ledNetStatus;
	int id;//拨码开关数值
	int isDiskExist;//是否存在离线存储设备
	U16 cmdTimeOut;//通讯超时秒数
	int isTimeOut;//是否通讯超时
	time_t cmdLastTime;//上一次通讯时间
	I64 mdTimeIntervalUS;//modbus公用寄存器的采集间隔，以微秒为单位
	U16 pwmFreq[3];//PWM分频系数
	U16 pwmHigh[3];//PWM高电平系数
	int userid;
	int threadCount; //net thread count
	long long diskTotal; // disk total size KBytes
	long long diskFree; // disk free size KBytes
	long long diskAvailable; // disk available size KBytes
	unsigned long diskCanRecord; // disk can save second of record data,
	U16 doValue;
	struct timeval eclkStart;
	I32 allWriteCount;
	I32 devType;
}DevPara;


inline int GetAllChCount( AdPara* pAd, IoPara* pIo );
void ExecuteCMD(const char *cmd, char *result);
int IsSDExist();
void InitParaFromSD( SDSet* pSD, DevPara* pDev, AdPara* pAD, IoPara* pIO );
int SDWriteFile(DevPara* pDev, char* pData, U32 bc, SDInfo* pSDInfo);
void SDFileClose(DevPara *pDev, SDInfo* pSDInfo);
void HCStart();
void HCStop();

#endif
